<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<style>
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote {
    margin: 0;
    padding: 0;
}
body {
    font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
    font-size: 13px;
    line-height: 18px;
    color: #737373;
    background-color: white;
    margin: 10px 13px 10px 13px;
}
table {
	margin: 10px 0 15px 0;
	border-collapse: collapse;
}
td,th {	
	border: 1px solid #ddd;
	padding: 3px 10px;
}
th {
	padding: 5px 10px;	
}

a {
    color: #0069d6;
}
a:hover {
    color: #0050a3;
    text-decoration: none;
}
a img {
    border: none;
}
p {
    margin-bottom: 9px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
    color: #404040;
    line-height: 36px;
}
h1 {
    margin-bottom: 18px;
    font-size: 30px;
}
h2 {
    font-size: 24px;
}
h3 {
    font-size: 18px;
}
h4 {
    font-size: 16px;
}
h5 {
    font-size: 14px;
}
h6 {
    font-size: 13px;
}
hr {
    margin: 0 0 19px;
    border: 0;
    border-bottom: 1px solid #ccc;
}
blockquote {
    padding: 13px 13px 21px 15px;
    margin-bottom: 18px;
    font-family:georgia,serif;
    font-style: italic;
}
blockquote:before {
    content:"\201C";
    font-size:40px;
    margin-left:-10px;
    font-family:georgia,serif;
    color:#eee;
}
blockquote p {
    font-size: 14px;
    font-weight: 300;
    line-height: 18px;
    margin-bottom: 0;
    font-style: italic;
}
code, pre {
    font-family: Monaco, Andale Mono, Courier New, monospace;
}
code {
    background-color: #fee9cc;
    color: rgba(0, 0, 0, 0.75);
    padding: 1px 3px;
    font-size: 12px;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
}
pre {
    display: block;
    padding: 14px;
    margin: 0 0 18px;
    line-height: 16px;
    font-size: 11px;
    border: 1px solid #d9d9d9;
    white-space: pre-wrap;
    word-wrap: break-word;
}
pre code {
    background-color: #fff;
    color:#737373;
    font-size: 11px;
    padding: 0;
}
sup {
    font-size: 0.83em;
    vertical-align: super;
    line-height: 0;
}
* {
	-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
    body {
        width: 854px;
        margin:10px auto;
    }
}
@media print {
	body,code,pre code,h1,h2,h3,h4,h5,h6 {
		color: black;
	}
	table, pre {
		page-break-inside: avoid;
	}
}
</style>
<title>图片和颜色</title>

</head>
<body>
<h2>图片和颜色</h2>

<h3>tint属性</h3>

<p>tint属性一个颜色值，可以对图片做颜色渲染，我们可以给view的背景设置tint色值，给ImageView的图片设置tint色值，也可以给任意Drawable或者NinePatchDrawable设置tint色值。</p>

<p>在应用的主题中也可以通过设置 <code>android:tint</code> 来给主题设置统一的颜色渲染。</p>

<p>tint的渲染模式有总共有16种，xml文件中可以使用6种，代码中我们可以设置16种，渲染模式决定了渲染颜色和原图颜色的取舍和合成规则：</p>

<p><img src="tintmode.png" alt="Mou icon" /></p>

<ol>
<li><code>PorterDuff.Mode.CLEAR</code> 所绘制不会提交到画布上。</li>
<li><code>PorterDuff.Mode.SRC</code> 显示上层绘制图片</li>
<li><code>PorterDuff.Mode.DST</code> 显示下层绘制图片</li>
<li><code>PorterDuff.Mode.SRC_OVER</code> 正常绘制显示，上下层绘制叠盖。</li>
<li><code>PorterDuff.Mode.DST_OVER</code> 上下层都显示。下层居上显示。</li>
<li><code>PorterDuff.Mode.SRC_IN</code> 取两层绘制交集。显示上层。</li>
<li><code>PorterDuff.Mode.DST_IN</code> 取两层绘制交集。显示下层。</li>
<li><code>PorterDuff.Mode.SRC_OUT</code> 取上层绘制非交集部分。</li>
<li><code>PorterDuff.Mode.DST_OUT</code> 取下层绘制非交集部分。</li>
<li><code>PorterDuff.Mode.SRC_ATOP</code> 取下层非交集部分与上层交集部分</li>
<li><code>PorterDuff.Mode.DST_ATOP</code> 取上层非交集部分与下层交集部分</li>
<li><code>PorterDuff.Mode.XOR</code> 取两层绘制非交集。两层绘制非交集。</li>
<li><code>PorterDuff.Mode.DARKEN</code> 上下层都显示。变暗</li>
<li><code>PorterDuff.Mode.LIGHTEN</code> 上下层都显示。变亮</li>
<li><code>PorterDuff.Mode.MULTIPLY</code> 取两层绘制交集</li>
<li><code>PorterDuff.Mode.SCREEN</code> 上下层都显示。</li>
</ol>


<p>通过tint色处理的图片会原图显示出不一样的颜色，我们可以通过这种方式利用一张图片做出图片选择器的效果，让控件在按压状态下显示另外一种颜色:</p>

<pre><code>通过给图片设置tint色生成另外一种图片
&lt;bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/ring"
        android:tintMode="multiply"
        android:tint="#5677fc" /&gt;
利用新的图片生成图片选择器
&lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
        &lt;item android:drawable="@drawable/tint_bitmap" android:state_pressed="true"/&gt;
        &lt;item android:drawable="@drawable/ring" /&gt;
&lt;/selector&gt;
</code></pre>

<h2>Palette调色版</h2>

<p>Palette调色板，可以很方便的让我们从图片中提取颜色。并且可以指定提取某种类型的颜色。</p>

<ol>
<li><code>Vibrant</code> 鲜艳的</li>
<li><code>Vibrant</code> dark鲜艳的暗色</li>
<li><code>Vibrant</code> light鲜艳的亮色</li>
<li><code>Muted</code> 柔和的</li>
<li><code>Muted</code> dark柔和的暗色</li>
<li><code>Muted</code> light柔和的亮色</li>
</ol>


<p>对图片取色是一个比较消耗性能的操作，其内部会对图片的像素值进来遍历以分析对比，所以我们要在异步线程中去完成。</p>

<pre><code>如果操作本来就属于后台线程，可以使用：
Palette p = Palette.generate(Bitmap bitmap);
如果在主线程中，我们可以使用异步的方式：
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
        public void onGenerated(Palette palette) {  }
});
</code></pre>

<p>当操作完成后或者异步回调后，我们就可以使用以下方式来获取对应的色值了，并且可以在没有获取到的情况下之指定默认值：</p>

<pre><code>p.getVibrantColor(int defaultColor);
p.getDarkVibrantColor(int defaultColor);
p.getLightVibrantColor(int defaultColor);
p.getMutedColor(int defaultColor);
p.getDarkMutedColor(int defaultColor);
p.getLightMutedColor(int defaultColor);
</code></pre>

<p>在使用palette之前，bitmap提供获取指定位置的像素值：</p>

<pre><code>bitmap.getPixel(x,y)
</code></pre>

<p>但是该方式只能获取某一点的像素值，palette是对整个bitmap的所有像素值进行分析，并选出几个像素占比比较多的像素值，这样选择出来的色值更符合图片的整体色值。</p>

<h2>vector矢量图</h2>

<p>矢量图也称为面向对象的图像或绘图图像，是计算机图形学中用点、直线或者多边形等基于数学方程的几何图元表示图像。矢量图形最大的优点是无论放大、缩小或旋转等不会失真；最大的缺点是难以表现色彩层次丰富的逼真图像效果。</p>

<p>Android L开始支持矢量图，我们可以用它来处理一些图形简单的icon，方便我们的适配。</p>

<p>Android L中对矢量图的支持是通过xml文件构建，通过矢量图的path描述来生成一个矢量图，对应的java对象为VectorDrawable。</p>

<p>下面是官方文档提供的一个矢量图，利用改文件，我们可以创建一个随意放大缩小都不会失真的心形</p>

<pre><code>&lt;vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:height="300dp"
        android:width="300dp"
        android:viewportHeight="40"
        android:viewportWidth="40"&gt;
        &lt;path android:fillColor="#ff00ff"
                android:pathData="M20.5,9.5
                        c-1.955,0,-3.83,1.268,-4.5,3
                        c-0.67,-1.732,-2.547,-3,-4.5,-3
                        C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5
                        c5.207,-5.242,9,-7.97,9,-11.5
                        C25,11.432,23.043,9.5,20.5,9.5z"/&gt;
&lt;/vector&gt;
</code></pre>

<p>矢量图的pathData数据就是用来描述矢量图的数学公式，其含义如下表：</p>

<table>
<thead>
<tr>
<th>命令类型 </th>
<th> 使用描述 </th>
<th> 代表含义 </th>
<th> 举例说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>移动指令  </td>
<td> M x,y </td>
<td> M移动绝对位置 </td>
<td> M 100,240</td>
</tr>
<tr>
<td>移动指令 </td>
<td> m x,y </td>
<td> m移动相对于上一个点 </td>
<td> m 100,240</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> L 或 l </td>
<td> 从当前点绘制直线到指定点 </td>
<td> L 100,100</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> H 或 h </td>
<td> 水平直线 </td>
<td> h 100</td>
</tr>
<tr>
<td>绘制指令  </td>
<td> V 或 v </td>
<td> 垂直直线  </td>
<td> v 100</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> C 或 c </td>
<td> 三次方程式贝塞尔曲线 </td>
<td> C 100,200 200,400 300,200</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> Q 或 q </td>
<td> 二次方程式贝塞尔曲线 </td>
<td> Q 100,200 300,200</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> S 或 s </td>
<td> 平滑三次方程式贝塞尔曲线 </td>
<td> S 100,200 200,400 300,200</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> T 或 t </td>
<td> 平滑二次方程式贝塞尔曲线 </td>
<td> T 100,200 300,200</td>
</tr>
<tr>
<td>绘制指令 </td>
<td> A 或 a </td>
<td> 椭圆 </td>
<td> A 5,5 0 0 1 10,10</td>
</tr>
<tr>
<td>关闭指令 </td>
<td> Z 或 z </td>
<td> 将图形的首、尾点用直线连接 </td>
<td> Z</td>
</tr>
<tr>
<td>填充规则 </td>
<td> F0 </td>
<td> EvenOdd 填充规则</td>
<td></td>
</tr>
<tr>
<td>填充规则 </td>
<td> F1 </td>
<td> Nonzero 填充规则</td>
<td></td>
</tr>
</tbody>
</table>


<p>通过path命令来进行简单的图形还是可行的，但是复杂的图形我们就需要借助工具来生成了，比如使用 Expression Design，就可以直接粘贴来自其它软件的矢量图形，然后选择导出，导出时做如后选择：文件->导出->导出属性->格式->XAML Silverlight 画布，即可得到XAML格式的矢量图形，也就是Path。</p>

<p>更多矢量图学习可参考：<a href="http://www.w3.org/TR/SVG11/paths.html#PathData">http://www.w3.org/TR/SVG11/paths.html#PathData</a>
我们可以访问http://editor.method.ac在线制作矢量图并导出path</p>
</body>
</html>